<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
    />
    <title>H5-五子棋</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        text-align: center;
        height: 100vh;
      }
      canvas {
        background-image: url(./images/20211227092309212.jpg);
        background-repeat: no-repeat;
        background-size: cover;
        background-position: center;
      }
    </style>
  </head>
  <body>
    <canvas></canvas>
    <script>
      class Gobang {
        constructor() {
          this.init();
          this.drawCheckerBroad();
          this.checkerBroadEvent();
        }

        init() {
          this.checkerBoradWidth = 20;
          this.lineNums = 19;
          this.blaorwh = '黄色';
          this.chessMartrixs = [];
          for (let i = 0; i <= this.lineNums; i++) {
            this.chessMartrixs.push(
              new Array(this.lineNums).fill(0, 0, this.lineNums)
            );
          }

          this.canvas = document.querySelector('canvas');
          this.canvas.width = this.checkerBoradWidth * (this.lineNums - 1);
          this.canvas.height = this.checkerBoradWidth * (this.lineNums - 1);
          this.ctx = this.canvas.getContext('2d');
        }

        drawCheckerBroad() {
          this.ctx.beginPath();
          this.ctx.strokeStyle = '#ccc';
          for (let i = 0; i < this.lineNums; i++) {
            this.ctx.moveTo(i * this.checkerBoradWidth, 0);
            this.ctx.lineTo(
              i * this.checkerBoradWidth,
              this.lineNums * this.checkerBoradWidth
            );
            this.ctx.moveTo(0, i * this.checkerBoradWidth);
            this.ctx.lineTo(
              this.lineNums * this.checkerBoradWidth,
              i * this.checkerBoradWidth
            );
          }
          this.ctx.stroke();
        }

        checkerBroadEvent() {
          this.canvas.addEventListener('click', (e) => {
            const x = e.offsetX;
            const y = e.offsetY;
            let arcX, arcY;
            let chessX, chessY;
            for (let i = 0; i <= this.lineNums; i++) {
              if (
                Math.abs(x - i * this.checkerBoradWidth) <=
                this.checkerBoradWidth / 2
              ) {
                arcX = i * this.checkerBoradWidth;
                chessX = i;
              }
              if (
                Math.abs(y - i * this.checkerBoradWidth) <=
                this.checkerBoradWidth / 2
              ) {
                arcY = i * this.checkerBoradWidth;
                chessY = i;
              }
            }
            if (arcX === undefined || arcY === undefined) return;

            if (this.chessMartrixs[chessY][chessX]) return;
            this.chessMartrixs[chessY][chessX] = this.blaorwh;
            this.ctx.beginPath();
            this.ctx.arc(
              arcX,
              arcY,
              this.checkerBoradWidth / 2,
              0,
              2 * Math.PI
            );

            if (this.blaorwh === '黄色') {
              this.ctx.fillStyle = 'yellow';
            } else {
              this.ctx.fillStyle = '#fff';
              this.ctx.stroke();
            }

            this.ctx.fill();
            if (
              this.victory(this.chessMartrixs, chessX, chessY, this.blaorwh)
            ) {
              console.log(this.blaorwh + '胜利');
              return;
            }
            this.blaorwh = this.blaorwh === '黄色' ? '白色' : '黄色';
          });
        }

        victory(matrix, x, y, borw) {
          let victoryUnits = [
            [-1, -1],
            [-1, 0],
            [1, -1],
            [0, 1],
          ];
          const getLineNums = (matrix, direcsx, x, y, borw) => {
            let results = 0;
            for (let i = 0; i < 5; i++) {
              const vicx = x + i * direcsx[0];
              const vicy = y + i * direcsx[1];
              if (
                matrix[vicy] !== undefined &&
                matrix[vicy][vicx] !== undefined &&
                borw === matrix[vicy][vicx]
              ) {
                results++;
              } else {
                break;
              }
            }
            return results;
          };

          const result = victoryUnits.some((item) => {
            const n1 = getLineNums(matrix, item, x, y, borw);
            const n2 = getLineNums(
              matrix,
              item.map((v) => -v),
              x,
              y,
              borw
            );
            return n1 + n2 - 1 >= 5;
          });
          return result;
        }
      }

      const gobang = new Gobang();
    </script>
  </body>
</html>
